<?php

class game {
    public $game = array();
    public $websocket;
    public $map  = array();//由客户端编号去找房间号

    function __construct($websocket) {
        $this->websocket = $websocket;

    }

    function event($buffer, $id, $socket) {
        $buffer = json_decode($buffer, true);

        switch($buffer['type']) {
            case 'createRoom':
                $roomId = mt_rand(100000, 999999);
                //$roomId = 1;
                $this->map[$id] = $roomId;
                $role = mt_rand(1, 2);//每次进入房间 随机决定是1号角色还是2号角色
                $this->game[$roomId] = [
                    'player1'    => [
                        'id'          => '',
                        //玩家的socket编号
                        'screenWidth' => '',
                        //屏幕宽度 用于生成星星的范围判断
                        'isHost'      => 0,
                        //是否房主 1是
                    ],
                    'player2'    => [
                        'id'          => '',
                        'screenWidth' => '',
                        'isHost'      => 0,
                    ],
                    //1空闲 2进行中
                    'gameStatus' => '1',
                    //比赛记录
                    'record'     => [],
                    //星星生成的限制 宽度 高度 地板高度 星星最小间距
                    'width' => 0,
                    'height' => 0,
                    'groundY' => 0,
                    'starDistance' => 0,
                    'starX' => 0
                ];
                $player                       = 'player' . $role; //player1 或 player2
                $this->game[$roomId][$player] = [
                    'id'          => $id,
                    'screenWidth' => $buffer['screenWidth'],
                    'isHost'      => 1,
                ];

                $return = [
                    'type'   => 'createRoom',
                    'msg'    => 'create success',
                    'roomId' => $roomId,
                    'role'   => $role
                ];
                $this->websocket->send(json_encode($return), $socket);
                break;
            case 'joinRoom':
                $roomId         = $buffer['roomId'];
                $this->map[$id] = $roomId;
                if(!isset($this->game[$roomId])) {
                    $return = [
                        'type' => 'error',
                        'msg'  => 'Room is not exist'
                    ];
                    $this->websocket->send(json_encode($return), $socket);
                    break;
                }

                //判断1号位还是2号位是空的 将新玩家的数据放入空位
                if($this->game[$roomId]['player1']['id'] == '') {
                    $player = 'player1';
                    $role   = 1;
                    $host = $this->game[$roomId]['player2']['id'];
                } else if($this->game[$roomId]['player2']['id'] == '') {
                    $player = 'player2';
                    $role   = 2;
                    $host = $this->game[$roomId]['player1']['id'];
                } else {
                    $return = [
                        'type' => 'error',
                        'msg'  => 'Room is full of player'
                    ];
                    $this->websocket->send(json_encode($return), $socket);
                    break;
                }

                $this->game[$roomId][$player] = [
                    'id'          => $id,
                    'screenWidth' => $buffer['screenWidth'],
                    'isHost'      => 0,
                ];
                //发送消息给房主 告知可以开始游戏
                $return_to_host = [
                    'type' => 'challengerJoinRoom'
                ];
                $this->websocket->send(json_encode($return_to_host), $host);

                //将游戏角色告知新加入的玩家
                $return = [
                    'type'   => 'joinRoom',
                    'roomId' => $roomId,
                    'role'   => $role
                ];
                $this->websocket->send(json_encode($return), $socket);
                break;
            case 'leaveRoom':
                $roomId = $this->map[$id];
                unset($this->map[$id]);
                if($this->game[$roomId]['player1']['id'] == $id) {
                    $player  = 'player1';
                    $newHost = 'player2';
                } else if($this->game[$roomId]['player2']['id'] == $id) {
                    $player  = 'player2';
                    $newHost = 'player1';
                }

                //如果房间里没有人了 销毁房间
                if($this->game[$roomId][$newHost]['id'] == '') {
                    unset($this->game[$roomId]);
                    break;
                }

                //给另一个玩家发送通知 有人离开房间了
                $this->game[$roomId][$player] = [
                    'id'          => '',
                    'screenWidth' => '',
                    'isHost'      => 0,
                ];
                $this->game[$roomId][$newHost]['isHost'] = 1;
                $return                                  = [
                    'type' => 'challengerLeaveRoom',
                ];
                $socket = $this->game[$roomId][$newHost]['id'];
                echo "剩下的玩家编号:", $socket,"\n";
                $this->websocket->send(json_encode($return), $socket);
                break;
            case 'gainScore' :
                $gainScore = true;
                $starid = $buffer['starid'];
                goto getNewStar;
                break;
            case 'gameStart':
                //游戏开始 向第二个玩家发送通知
                $roomId = $this->map[$id];
                $challengerSocket = $this->_getChallengerSocket($id);
                $return = [
                    'type' => 'gameStart',
                ];
                //获取两个玩家的设备宽度 取小的一个 作为星星生成范围的限制
                $width = min($this->game[$roomId]['player1']['screenWidth'], $this->game[$roomId]['player2']['screenWidth']);
                $this->game[$roomId]['width'] = $width;
                $this->game[$roomId]['height'] = $buffer['jumpHeight'];
                $this->game[$roomId]['groundY'] = $buffer['groundY'];
                $this->game[$roomId]['starDistance'] = $buffer['starDistance'];
                $this->websocket->send(json_encode($return), $challengerSocket);
                //break;
            case 'getNewStar':
                $gainScore = false;
                getNewStar:
                //星星被吃掉了 或者到时间消失了 需要一个新的星星的位置
                $roomId = $this->map[$id];
                $game = $this->game[$roomId];
                do {
                    // 根据屏幕宽度，随机得到一个星星 x 坐标
                    $maxX = $game['width'] / 2;
                    $randX = mt_rand(-100, 100) * $maxX / 100;
                    //如果新的星星和上一颗星星离的太近 需要重新生成
                } while (abs($randX - $game['starX']) < $game['starDistance']);

                //$randX = 0;

                $this->game[$roomId]['starX'] = $randX;

                // 根据地平面位置和主角跳跃高度，随机得到一个星星的 y 坐标
                $randY = $game['groundY'] + (mt_rand(0, 100) * $game['height'] / 100) + 50;
                //if($randY < 50) $randY = 50;
                //$randY = 150;

                if ($gainScore == true) {
                    if ($starid != $game['starid']) {
                        //
                        return;
                    }
                }

                $starid = uniqid();
                $this->game[$roomId]['starid'] = $starid;
                $challengerSocket = $this->_getChallengerSocket($id);
                $return = [
                    'type' => 'buildStar',
                    'x' => $randX,
                    'y' => $randY,
                    'starid' => $starid, // 星星的唯一id 防止多人同时吃到 加分判断出问题
                    'selfGainScore' => 1
                ];
                $this->websocket->send(json_encode($return), $socket);
                if ($gainScore == true) {
                    $return = [
                        'type' => 'buildStar',
                        'x' => $randX,
                        'y' => $randY,
                        'starid' => $starid,
                        'challengerGainScore' => '1'
                    ];
                }
                $this->websocket->send(json_encode($return), $challengerSocket);
                break;
            //每帧玩家位置的同步
            case 'positionChange':
                $challengerSocket = $this->_getChallengerSocket($id);
                $return = [
                    'type' => 'positionChange',
                    'x' => $buffer['x'],
                    'y' => $buffer['y']
                ];
                $this->websocket->send(json_encode($return), $challengerSocket);
                break;
            case 'gameOver':
                break;
            default:
                $return = [
                    'type' => 'Unidentified message',
                ];
                $this->websocket->send(json_encode($return), $socket);
                break;
        }
    }

    //获取房间内另一个玩家的socket连接
    private function _getChallengerSocket($id) {
        $roomId = $this->map[$id];
        if($this->game[$roomId]['player1']['id'] == $id) {
            $challenger  = 'player2';
        } else if($this->game[$roomId]['player2']['id'] == $id) {
            $challenger  = 'player1';
        }
        $challengerId = $this->game[$roomId][$challenger]['id'];
        return $challengerId;
    }
}